123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/system/status_area_widget.h"
- #include "ash/capture_mode/stop_recording_button_tray.h"
- #include "ash/constants/ash_features.h"
- #include "ash/constants/ash_switches.h"
- #include "ash/keyboard/ui/keyboard_ui_controller.h"
- #include "ash/projector/projector_annotation_tray.h"
- #include "ash/public/cpp/shelf_config.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shelf/shelf.h"
- #include "ash/shelf/shelf_layout_manager.h"
- #include "ash/shelf/shelf_widget.h"
- #include "ash/shell.h"
- #include "ash/system/accessibility/dictation_button_tray.h"
- #include "ash/system/accessibility/select_to_speak/select_to_speak_tray.h"
- #include "ash/system/eche/eche_tray.h"
- #include "ash/system/holding_space/holding_space_tray.h"
- #include "ash/system/ime_menu/ime_menu_tray.h"
- #include "ash/system/media/media_tray.h"
- #include "ash/system/model/clock_model.h"
- #include "ash/system/model/system_tray_model.h"
- #include "ash/system/overview/overview_button_tray.h"
- #include "ash/system/palette/palette_tray.h"
- #include "ash/system/phonehub/phone_hub_tray.h"
- #include "ash/system/session/logout_button_tray.h"
- #include "ash/system/status_area_widget_delegate.h"
- #include "ash/system/tray/status_area_overflow_button_tray.h"
- #include "ash/system/tray/tray_background_view.h"
- #include "ash/system/tray/tray_constants.h"
- #include "ash/system/tray/tray_container.h"
- #include "ash/system/unified/date_tray.h"
- #include "ash/system/unified/unified_system_tray.h"
- #include "ash/system/virtual_keyboard/virtual_keyboard_tray.h"
- #include "ash/wm/tablet_mode/tablet_mode_controller.h"
- #include "base/command_line.h"
- #include "base/containers/adapters.h"
- #include "base/i18n/time_formatting.h"
- #include "base/metrics/histogram_macros.h"
- #include "chromeos/ash/services/assistant/public/cpp/features.h"
- #include "media/base/media_switches.h"
- #include "ui/compositor/layer.h"
- #include "ui/compositor/scoped_layer_animation_settings.h"
- #include "ui/display/display.h"
- namespace ash {
- ////////////////////////////////////////////////////////////////////////////////
- // StatusAreaWidget::ScopedTrayBubbleCounter
- StatusAreaWidget::ScopedTrayBubbleCounter::ScopedTrayBubbleCounter(
- StatusAreaWidget* status_area_widget)
- : status_area_widget_(status_area_widget->weak_ptr_factory_.GetWeakPtr()) {
- if (status_area_widget_->tray_bubble_count_ == 0) {
- status_area_widget_->shelf()
- ->shelf_layout_manager()
- ->OnShelfTrayBubbleVisibilityChanged(/*bubble_shown=*/true);
- }
- ++status_area_widget_->tray_bubble_count_;
- }
- StatusAreaWidget::ScopedTrayBubbleCounter::~ScopedTrayBubbleCounter() {
- // ScopedTrayBubbleCounter may live longer than StatusAreaWidget.
- if (!status_area_widget_)
- return;
- --status_area_widget_->tray_bubble_count_;
- if (status_area_widget_->tray_bubble_count_ == 0) {
- status_area_widget_->shelf()
- ->shelf_layout_manager()
- ->OnShelfTrayBubbleVisibilityChanged(/*bubble_shown=*/false);
- }
- DCHECK_GE(status_area_widget_->tray_bubble_count_, 0);
- }
- ////////////////////////////////////////////////////////////////////////////////
- // StatusAreaWidget
- StatusAreaWidget::StatusAreaWidget(aura::Window* status_container, Shelf* shelf)
- : status_area_widget_delegate_(new StatusAreaWidgetDelegate(shelf)),
- shelf_(shelf) {
- DCHECK(status_container);
- DCHECK(shelf);
- views::Widget::InitParams params(
- views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params.delegate = status_area_widget_delegate_;
- params.name = "StatusAreaWidget";
- params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = status_container;
- Init(std::move(params));
- set_focus_on_creation(false);
- SetContentsView(status_area_widget_delegate_);
- }
- void StatusAreaWidget::Initialize() {
- DCHECK(!initialized_);
- // Create the child views, left to right.
- overflow_button_tray_ =
- AddTrayButton(std::make_unique<StatusAreaOverflowButtonTray>(shelf_));
- holding_space_tray_ =
- AddTrayButton(std::make_unique<HoldingSpaceTray>(shelf_));
- logout_button_tray_ =
- AddTrayButton(std::make_unique<LogoutButtonTray>(shelf_));
- dictation_button_tray_ =
- AddTrayButton(std::make_unique<DictationButtonTray>(shelf_));
- select_to_speak_tray_ =
- AddTrayButton(std::make_unique<SelectToSpeakTray>(shelf_));
- ime_menu_tray_ = AddTrayButton(std::make_unique<ImeMenuTray>(shelf_));
- virtual_keyboard_tray_ =
- AddTrayButton(std::make_unique<VirtualKeyboardTray>(shelf_));
- stop_recording_button_tray_ =
- AddTrayButton(std::make_unique<StopRecordingButtonTray>(shelf_));
- if (features::IsProjectorAnnotatorEnabled()) {
- projector_annotation_tray_ =
- AddTrayButton(std::make_unique<ProjectorAnnotationTray>(shelf_));
- }
- palette_tray_ = AddTrayButton(std::make_unique<PaletteTray>(shelf_));
- if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsForChromeOS)) {
- media_tray_ = AddTrayButton(std::make_unique<MediaTray>(shelf_));
- }
- if (chromeos::features::IsEcheSWAEnabled()) {
- eche_tray_ = AddTrayButton(std::make_unique<EcheTray>(shelf_));
- }
- if (chromeos::features::IsPhoneHubEnabled()) {
- phone_hub_tray_ = AddTrayButton(std::make_unique<PhoneHubTray>(shelf_));
- }
- auto unified_system_tray = std::make_unique<UnifiedSystemTray>(shelf_);
- unified_system_tray_ = unified_system_tray.get();
- if (features::IsCalendarViewEnabled()) {
- date_tray_ =
- AddTrayButton(std::make_unique<DateTray>(shelf_, unified_system_tray_));
- }
- AddTrayButton(std::move(unified_system_tray));
- overview_button_tray_ =
- AddTrayButton(std::make_unique<OverviewButtonTray>(shelf_));
- // Each tray_button's animation will be disabled for the life time of this
- // local `animation_disablers`, which means the closures to enable the
- // animation will be executed when it's out of this method (Initialize())
- // scope.
- std::list<base::ScopedClosureRunner> animation_disablers;
- // Initialize after all trays have been created.
- for (TrayBackgroundView* tray_button : tray_buttons_) {
- tray_button->Initialize();
- animation_disablers.push_back(tray_button->DisableShowAnimation());
- }
- EnsureTrayOrder();
- UpdateAfterLoginStatusChange(
- Shell::Get()->session_controller()->login_status());
- UpdateLayout(/*animate=*/false);
- Shell::Get()->session_controller()->AddObserver(this);
- // NOTE: Container may be hidden depending on login/display state.
- Show();
- initialized_ = true;
- }
- StatusAreaWidget::~StatusAreaWidget() {
- Shell::Get()->session_controller()->RemoveObserver(this);
- status_area_widget_delegate_->Shutdown();
- }
- // static
- StatusAreaWidget* StatusAreaWidget::ForWindow(aura::Window* window) {
- return Shelf::ForWindow(window)->status_area_widget();
- }
- void StatusAreaWidget::UpdateAfterLoginStatusChange(LoginStatus login_status) {
- if (login_status_ == login_status)
- return;
- login_status_ = login_status;
- for (TrayBackgroundView* tray_button : tray_buttons_)
- tray_button->UpdateAfterLoginStatusChange();
- }
- void StatusAreaWidget::SetSystemTrayVisibility(bool visible) {
- TrayBackgroundView* tray = unified_system_tray_;
- tray->SetVisiblePreferred(visible);
- if (features::IsCalendarViewEnabled())
- date_tray_->SetVisiblePreferred(visible);
- if (visible) {
- Show();
- } else {
- tray->CloseBubble();
- Hide();
- }
- }
- void StatusAreaWidget::OnSessionStateChanged(
- session_manager::SessionState state) {
- for (TrayBackgroundView* tray_button : tray_buttons_)
- tray_button->UpdateBackground();
- }
- void StatusAreaWidget::UpdateCollapseState() {
- collapse_state_ = CalculateCollapseState();
- if (collapse_state_ == CollapseState::COLLAPSED) {
- CalculateButtonVisibilityForCollapsedState();
- } else {
- // All tray buttons are visible when the status area is not collapsible.
- // This is the most common state. They are also all visible when the status
- // area is expanded by the user.
- overflow_button_tray_->SetVisiblePreferred(collapse_state_ ==
- CollapseState::EXPANDED);
- for (TrayBackgroundView* tray_button : tray_buttons_) {
- tray_button->set_show_when_collapsed(true);
- tray_button->UpdateAfterStatusAreaCollapseChange();
- }
- }
- status_area_widget_delegate_->OnStatusAreaCollapseStateChanged(
- collapse_state_);
- }
- void StatusAreaWidget::LogVisiblePodCountMetric() {
- int visible_pod_count = 0;
- for (auto* tray_button : tray_buttons_) {
- if (tray_button == overflow_button_tray_ ||
- tray_button == overview_button_tray_ ||
- tray_button == unified_system_tray_ || tray_button == date_tray_ ||
- !tray_button->GetVisible()) {
- continue;
- }
- visible_pod_count += 1;
- }
- if (Shell::Get()->tablet_mode_controller()->InTabletMode()) {
- UMA_HISTOGRAM_COUNTS_100("ChromeOS.SystemTray.Tablet.ShelfPodCount",
- visible_pod_count);
- } else {
- UMA_HISTOGRAM_COUNTS_100("ChromeOS.SystemTray.ShelfPodCount",
- visible_pod_count);
- }
- }
- void StatusAreaWidget::CalculateTargetBounds() {
- for (TrayBackgroundView* tray_button : tray_buttons_)
- tray_button->CalculateTargetBounds();
- status_area_widget_delegate_->CalculateTargetBounds();
- gfx::Size status_size(status_area_widget_delegate_->GetTargetBounds().size());
- const gfx::Size shelf_size = shelf_->shelf_widget()->GetTargetBounds().size();
- const gfx::Point shelf_origin =
- shelf_->shelf_widget()->GetTargetBounds().origin();
- if (shelf_->IsHorizontalAlignment())
- status_size.set_height(shelf_size.height());
- else
- status_size.set_width(shelf_size.width());
- gfx::Point status_origin = shelf_->SelectValueForShelfAlignment(
- gfx::Point(0, 0),
- gfx::Point(shelf_size.width() - status_size.width(),
- shelf_size.height() - status_size.height()),
- gfx::Point(0, shelf_size.height() - status_size.height()));
- if (shelf_->IsHorizontalAlignment() && !base::i18n::IsRTL())
- status_origin.set_x(shelf_size.width() - status_size.width());
- status_origin.Offset(shelf_origin.x(), shelf_origin.y());
- target_bounds_ = gfx::Rect(status_origin, status_size);
- }
- gfx::Rect StatusAreaWidget::GetTargetBounds() const {
- return target_bounds_;
- }
- void StatusAreaWidget::UpdateLayout(bool animate) {
- const LayoutInputs new_layout_inputs = GetLayoutInputs();
- if (layout_inputs_ == new_layout_inputs)
- return;
- if (!new_layout_inputs.should_animate)
- animate = false;
- for (TrayBackgroundView* tray_button : tray_buttons_)
- tray_button->UpdateLayout();
- status_area_widget_delegate_->UpdateLayout(animate);
- // Having a window which is visible but does not have an opacity is an
- // illegal state.
- ui::Layer* layer = GetNativeView()->layer();
- layer->SetOpacity(new_layout_inputs.opacity);
- if (new_layout_inputs.opacity)
- ShowInactive();
- else
- Hide();
- ui::ScopedLayerAnimationSettings animation_setter(layer->GetAnimator());
- animation_setter.SetTransitionDuration(
- animate ? ShelfConfig::Get()->shelf_animation_duration()
- : base::Milliseconds(0));
- animation_setter.SetTweenType(gfx::Tween::EASE_OUT);
- animation_setter.SetPreemptionStrategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- SetBounds(new_layout_inputs.bounds);
- layout_inputs_ = new_layout_inputs;
- }
- void StatusAreaWidget::UpdateTargetBoundsForGesture(int shelf_position) {
- if (shelf_->IsHorizontalAlignment())
- target_bounds_.set_y(shelf_position);
- else
- target_bounds_.set_x(shelf_position);
- }
- void StatusAreaWidget::HandleLocaleChange() {
- // Here we force the layer's bounds to be updated for text direction (if
- // needed).
- status_area_widget_delegate_->RemoveAllChildViewsWithoutDeleting();
- for (auto* tray_button : tray_buttons_) {
- tray_button->HandleLocaleChange();
- status_area_widget_delegate_->AddChildView(tray_button);
- }
- EnsureTrayOrder();
- }
- void StatusAreaWidget::NotifyAnyBubbleVisibilityChanged(
- views::Widget* bubble_widget,
- bool visible) {
- for (auto* tray_button : tray_buttons_) {
- tray_button->OnAnyBubbleVisibilityChanged(bubble_widget, visible);
- }
- }
- void StatusAreaWidget::CalculateButtonVisibilityForCollapsedState() {
- if (!initialized_)
- return;
- DCHECK(collapse_state_ == CollapseState::COLLAPSED);
- bool force_collapsible = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAshForceStatusAreaCollapsible);
- // If |stop_recording_button_tray_| is visible, make some space in tray for
- // it.
- const int stop_recording_button_width =
- stop_recording_button_tray_->visible_preferred()
- ? stop_recording_button_tray_->GetPreferredSize().width()
- : 0;
- // We update visibility of each tray button based on the available width.
- const int available_width = GetCollapseAvailableWidth(force_collapsible) -
- stop_recording_button_width;
- // First, reset all tray button to be hidden.
- overflow_button_tray_->ResetStateToCollapsed();
- for (TrayBackgroundView* tray_button : tray_buttons_)
- tray_button->set_show_when_collapsed(false);
- // Iterate backwards making tray buttons visible until |available_width| is
- // exceeded.
- TrayBackgroundView* previous_tray = nullptr;
- bool show_overflow_button = false;
- int used_width = 0;
- for (TrayBackgroundView* tray : base::Reversed(tray_buttons_)) {
- // Skip non-enabled tray buttons.
- if (!tray->visible_preferred())
- continue;
- // Skip |stop_recording_button_tray_| since it's always visible.
- if (tray == stop_recording_button_tray_)
- continue;
- // Show overflow button once available width is exceeded.
- int tray_width = tray->tray_container()->GetPreferredSize().width();
- if (used_width + tray_width > available_width) {
- show_overflow_button = true;
- // Maybe remove the last tray button to make room for the overflow tray.
- int overflow_button_width =
- overflow_button_tray_->GetPreferredSize().width();
- if (previous_tray && used_width + overflow_button_width > available_width)
- previous_tray->set_show_when_collapsed(false);
- break;
- }
- tray->set_show_when_collapsed(true);
- previous_tray = tray;
- used_width += tray_width;
- }
- // Skip |stop_recording_button_tray_| so it's always visible.
- if (stop_recording_button_tray_->visible_preferred())
- stop_recording_button_tray_->set_show_when_collapsed(true);
- overflow_button_tray_->SetVisiblePreferred(show_overflow_button);
- overflow_button_tray_->UpdateAfterStatusAreaCollapseChange();
- for (TrayBackgroundView* tray_button : tray_buttons_)
- tray_button->UpdateAfterStatusAreaCollapseChange();
- }
- void StatusAreaWidget::EnsureTrayOrder() {
- if (projector_annotation_tray_) {
- status_area_widget_delegate_->ReorderChildView(projector_annotation_tray_,
- 1);
- }
- status_area_widget_delegate_->ReorderChildView(
- stop_recording_button_tray_, projector_annotation_tray_ ? 2 : 1);
- }
- StatusAreaWidget::CollapseState StatusAreaWidget::CalculateCollapseState()
- const {
- // The status area is only collapsible in tablet mode. Otherwise, we just show
- // all trays.
- if (!Shell::Get()->tablet_mode_controller())
- return CollapseState::NOT_COLLAPSIBLE;
- // An update may occur during initialization of the shelf, so just skip it.
- if (!initialized_)
- return CollapseState::NOT_COLLAPSIBLE;
- bool is_collapsible =
- Shell::Get()->tablet_mode_controller()->InTabletMode() &&
- ShelfConfig::Get()->is_in_app();
- bool force_collapsible = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAshForceStatusAreaCollapsible);
- is_collapsible |= force_collapsible;
- CollapseState state = CollapseState::NOT_COLLAPSIBLE;
- if (is_collapsible) {
- // Update the collapse state based on the previous overflow button state.
- state = overflow_button_tray_->state() ==
- StatusAreaOverflowButtonTray::CLICK_TO_EXPAND
- ? CollapseState::COLLAPSED
- : CollapseState::EXPANDED;
- } else {
- state = CollapseState::NOT_COLLAPSIBLE;
- }
- if (state == CollapseState::COLLAPSED) {
- // We might not need to be collapsed, if there is enough space for all the
- // buttons.
- const int available_width = GetCollapseAvailableWidth(force_collapsible);
- int used_width = 0;
- for (TrayBackgroundView* tray : base::Reversed(tray_buttons_)) {
- // If we reach the final overflow tray button, then all the tray buttons
- // fit and there is no need for a collapse state.
- if (tray == overflow_button_tray_)
- return CollapseState::NOT_COLLAPSIBLE;
- // Skip non-enabled tray buttons.
- if (!tray->visible_preferred())
- continue;
- int tray_width = tray->tray_container()->GetPreferredSize().width();
- if (used_width + tray_width > available_width)
- break;
- used_width += tray_width;
- }
- }
- return state;
- }
- TrayBackgroundView* StatusAreaWidget::GetSystemTrayAnchor() const {
- // Use the target visibility of the layer instead of the visibility of the
- // view because the view is still visible when fading away, but we do not want
- // to anchor to this element in that case.
- if (overview_button_tray_->layer()->GetTargetVisibility())
- return overview_button_tray_;
- return unified_system_tray_;
- }
- gfx::Rect StatusAreaWidget::GetMediaTrayAnchorRect() const {
- if (!media_tray_)
- return gfx::Rect();
- // Calculate anchor rect of media tray bubble. This is required because the
- // bubble can be visible while the tray button is hidden. (e.g. when user
- // clicks the unpin button in the dialog, which will not close the dialog)
- bool found_media_tray = false;
- int offset = 0;
- // Accumulate the width/height of all visible tray buttons after media tray.
- for (views::View* tray_button : tray_buttons_) {
- if (tray_button == media_tray_) {
- found_media_tray = true;
- continue;
- }
- if (!found_media_tray || !tray_button->GetVisible())
- continue;
- offset += shelf_->IsHorizontalAlignment() ? tray_button->width()
- : tray_button->height();
- }
- // Use system tray anchor view (system tray or overview button tray if
- // visible) to find media tray button's origin.
- gfx::Rect system_tray_bounds = GetSystemTrayAnchor()->GetBoundsInScreen();
- switch (shelf_->alignment()) {
- case ShelfAlignment::kBottom:
- case ShelfAlignment::kBottomLocked:
- if (base::i18n::IsRTL()) {
- return gfx::Rect(system_tray_bounds.origin() + gfx::Vector2d(offset, 0),
- gfx::Size());
- } else {
- return gfx::Rect(
- system_tray_bounds.top_right() - gfx::Vector2d(offset, 0),
- gfx::Size());
- }
- case ShelfAlignment::kLeft:
- return gfx::Rect(
- system_tray_bounds.bottom_right() - gfx::Vector2d(0, offset),
- gfx::Size());
- case ShelfAlignment::kRight:
- return gfx::Rect(
- system_tray_bounds.bottom_left() - gfx::Vector2d(0, offset),
- gfx::Size());
- }
- NOTREACHED();
- return gfx::Rect();
- }
- bool StatusAreaWidget::ShouldShowShelf() const {
- // If it has main bubble, return true.
- if (unified_system_tray_->IsBubbleShown())
- return true;
- // If any tray is showing a context menu, the shelf should be visible.
- for (TrayBackgroundView* tray_button : tray_buttons_) {
- if (tray_button->IsShowingMenu())
- return true;
- }
- // If it has a slider bubble, return false.
- if (unified_system_tray_->IsSliderBubbleShown())
- return false;
- // All other tray bubbles on the same display with status area widget will
- // force the shelf to be visible.
- return tray_bubble_count_ > 0;
- }
- bool StatusAreaWidget::IsMessageBubbleShown() const {
- return unified_system_tray_->IsBubbleShown();
- }
- void StatusAreaWidget::SchedulePaint() {
- for (TrayBackgroundView* tray_button : tray_buttons_)
- tray_button->SchedulePaint();
- }
- bool StatusAreaWidget::OnNativeWidgetActivationChanged(bool active) {
- if (!Widget::OnNativeWidgetActivationChanged(active))
- return false;
- if (active)
- status_area_widget_delegate_->SetPaneFocusAndFocusDefault();
- return true;
- }
- void StatusAreaWidget::OnMouseEvent(ui::MouseEvent* event) {
- if (event->IsMouseWheelEvent()) {
- ui::MouseWheelEvent* mouse_wheel_event = event->AsMouseWheelEvent();
- shelf_->ProcessMouseWheelEvent(mouse_wheel_event);
- return;
- }
- // Clicking anywhere except the virtual keyboard tray icon should hide the
- // virtual keyboard.
- gfx::Point location = event->location();
- views::View::ConvertPointFromWidget(virtual_keyboard_tray_, &location);
- if (event->type() == ui::ET_MOUSE_PRESSED &&
- !virtual_keyboard_tray_->HitTestPoint(location)) {
- keyboard::KeyboardUIController::Get()->HideKeyboardImplicitlyByUser();
- }
- views::Widget::OnMouseEvent(event);
- }
- void StatusAreaWidget::OnGestureEvent(ui::GestureEvent* event) {
- // Tapping anywhere except the virtual keyboard tray icon should hide the
- // virtual keyboard.
- gfx::Point location = event->location();
- views::View::ConvertPointFromWidget(virtual_keyboard_tray_, &location);
- if (event->type() == ui::ET_GESTURE_TAP_DOWN &&
- !virtual_keyboard_tray_->HitTestPoint(location)) {
- keyboard::KeyboardUIController::Get()->HideKeyboardImplicitlyByUser();
- }
- views::Widget::OnGestureEvent(event);
- }
- void StatusAreaWidget::OnScrollEvent(ui::ScrollEvent* event) {
- shelf_->ProcessScrollEvent(event);
- if (!event->handled())
- views::Widget::OnScrollEvent(event);
- }
- template <typename TrayButtonT>
- TrayButtonT* StatusAreaWidget::AddTrayButton(
- std::unique_ptr<TrayButtonT> tray_button) {
- tray_buttons_.push_back(tray_button.get());
- return status_area_widget_delegate_->AddChildView(std::move(tray_button));
- }
- // Specialization declared here for use in tests.
- template TrayBackgroundView* StatusAreaWidget::AddTrayButton<
- TrayBackgroundView>(std::unique_ptr<TrayBackgroundView> tray_button);
- StatusAreaWidget::LayoutInputs StatusAreaWidget::GetLayoutInputs() const {
- unsigned int child_visibility_bitmask = 0;
- DCHECK(tray_buttons_.size() <
- std::numeric_limits<decltype(child_visibility_bitmask)>::digits);
- for (unsigned int i = 0; i < tray_buttons_.size(); ++i) {
- if (tray_buttons_[i]->GetVisible())
- child_visibility_bitmask |= 1 << i;
- }
- bool should_animate = true;
- // Do not animate when tray items are added and removed (See
- // crbug.com/1067199).
- if (layout_inputs_) {
- const bool is_horizontal_alignment = shelf_->IsHorizontalAlignment();
- const gfx::Rect current_bounds = layout_inputs_->bounds;
- if ((is_horizontal_alignment &&
- current_bounds.width() != target_bounds_.width()) ||
- (!is_horizontal_alignment &&
- current_bounds.height() != target_bounds_.height())) {
- should_animate = false;
- }
- }
- return {target_bounds_, CalculateCollapseState(),
- shelf_->shelf_layout_manager()->GetOpacity(),
- child_visibility_bitmask, should_animate};
- }
- int StatusAreaWidget::GetCollapseAvailableWidth(bool force_collapsible) const {
- const int shelf_width =
- shelf_->shelf_widget()->GetClientAreaBoundsInScreen().width();
- if (!force_collapsible)
- return shelf_width / 2 - kStatusAreaLeftPaddingForOverflow;
- int available_width = kStatusAreaForceCollapseAvailableWidth;
- // If calendar view is enabled, add the date tray width to the collapse
- // available width.
- if (features::IsCalendarViewEnabled()) {
- DCHECK(date_tray_);
- available_width += date_tray_->tray_container()->GetPreferredSize().width();
- }
- return available_width;
- }
- } // namespace ash
|