1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153

ash / shelf / shelf_navigation_widget.h [blame]

// 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_SHELF_SHELF_NAVIGATION_WIDGET_H_
#define ASH_SHELF_SHELF_NAVIGATION_WIDGET_H_

#include <memory>

#include "ash/ash_export.h"
#include "ash/shelf/shelf_component.h"
#include "base/memory/raw_ptr.h"
#include "ui/views/accessible_pane_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace aura {
class Window;
}

namespace views {
class BoundsAnimator;
}

namespace ash {
class BackButton;
class HomeButton;
enum class HotseatState;
class NavigationButtonAnimationMetricsReporter;
class Shelf;
class ShelfView;

// The shelf navigation widget holds the home button and (when in tablet mode)
// the back button.
class ASH_EXPORT ShelfNavigationWidget : public ShelfComponent,
                                         public views::Widget {
 public:
  class TestApi {
   public:
    explicit TestApi(ShelfNavigationWidget* widget);
    ~TestApi();

    // Whether the home button view is visible.
    bool IsHomeButtonVisible() const;

    // Whether the back button view is visible.
    bool IsBackButtonVisible() const;

    views::BoundsAnimator* GetBoundsAnimator();

    views::View* GetWidgetDelegateView();

   private:
    raw_ptr<ShelfNavigationWidget> navigation_widget_;
  };

  ShelfNavigationWidget(Shelf* shelf, ShelfView* shelf_view);

  ShelfNavigationWidget(const ShelfNavigationWidget&) = delete;
  ShelfNavigationWidget& operator=(const ShelfNavigationWidget&) = delete;

  ~ShelfNavigationWidget() override;

  // Initializes the widget, sets its contents view and basic properties.
  void Initialize(aura::Window* container);

  // views::Widget:
  void OnMouseEvent(ui::MouseEvent* event) override;
  void OnScrollEvent(ui::ScrollEvent* event) override;
  bool OnNativeWidgetActivationChanged(bool active) override;
  void OnGestureEvent(ui::GestureEvent* event) override;

  // Getter for the back button view - nullptr if the back button should not be
  // shown for the current shelf configuration.
  BackButton* GetBackButton() const;

  // Getter for the home button view - nullptr if the home button should not be
  // shown for  the current shelf configuration.
  HomeButton* GetHomeButton() const;

  // Sets whether the last focusable child (instead of the first) should be
  // focused when activating this widget.
  void SetDefaultLastFocusableChild(bool default_last_focusable_child);

  // ShelfComponent:
  void CalculateTargetBounds() override;
  gfx::Rect GetTargetBounds() const override;
  void UpdateLayout(bool animate) override;
  void UpdateTargetBoundsForGesture(int shelf_position) override;

  // Returns the visible part's bounds in screen coordinates.
  gfx::Rect GetVisibleBounds() const;

  // Do preparations before setting focus on the navigation widget.
  void PrepareForGettingFocus(bool last_element);

  // Called when shelf layout manager detects a locale change. Reloads the
  // home and back button tooltips and accessibility name strings.
  void HandleLocaleChange();

  const views::BoundsAnimator* bounds_animator_for_test() const {
    return bounds_animator_.get();
  }

 private:
  class Delegate;

  void UpdateButtonVisibility(
      views::View* button,
      bool visible,
      bool animate,
      NavigationButtonAnimationMetricsReporter* metrics_reporter,
      HotseatState target_hotseat_state);

  // Returns the clip rectangle in the shelf navigation widget's coordinates.
  // The returned rectangle is mirrored under RTL.
  gfx::Rect CalculateClipRectAfterRTL() const;

  // Returns the ideal size of the whole widget or the visible area only when
  // |only_visible_area| is true.
  gfx::Size CalculateIdealSize(bool only_visible_area) const;

  // Returns the number of visible control buttons.
  int CalculateButtonCount() const;

  raw_ptr<Shelf> shelf_ = nullptr;
  raw_ptr<Delegate> delegate_ = nullptr;

  // In tablet mode with hotseat enabled, `clip_rect_after_rtl_` is used to hide
  // the invisible widget part. We try best to avoid changing the widget's
  // bounds and use layer clip instead. `clip_rect_after_rtl_` is mirrored under
  // RTL.
  gfx::Rect clip_rect_after_rtl_;

  // The target widget bounds in screen coordinates.
  gfx::Rect target_bounds_;

  std::unique_ptr<views::BoundsAnimator> bounds_animator_;

  // Animation metrics reporter for back button animations. Owned by the
  // Widget to ensure it outlives the BackButton view.
  std::unique_ptr<NavigationButtonAnimationMetricsReporter>
      back_button_metrics_reporter_;

  // Animation metrics reporter for home button animations. Owned by the
  // Widget to ensure it outlives the HomeButton view.
  std::unique_ptr<NavigationButtonAnimationMetricsReporter>
      home_button_metrics_reporter_;
};

}  // namespace ash

#endif  // ASH_SHELF_SHELF_NAVIGATION_WIDGET_H_