chromium/ash/public/cpp/shelf_config.h

// 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_PUBLIC_CPP_SHELF_CONFIG_H_
#define ASH_PUBLIC_CPP_SHELF_CONFIG_H_

#include <optional>

#include "ash/ash_export.h"
#include "ash/public/cpp/app_list/app_list_controller_observer.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/model/virtual_keyboard_model.h"
#include "ash/wm/overview/overview_observer.h"
#include "ash/wm/splitview/split_view_observer.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/color/color_id.h"
#include "ui/display/display_observer.h"
#include "ui/gfx/animation/tween.h"

namespace base {
class TimeDelta;
}

namespace session_manager {
enum class SessionState;
}  // namespace session_manager

namespace ash {

// Provides layout and drawing config for the Shelf. Note That some of these
// values could change at runtime.
class ASH_EXPORT ShelfConfig : public SessionObserver,
                               public AppListControllerObserver,
                               public display::DisplayObserver,
                               public VirtualKeyboardModel::Observer,
                               public OverviewObserver {
 public:
  class Observer : public base::CheckedObserver {
   public:
    // Invoked when shelf config values are changed.
    virtual void OnShelfConfigUpdated() {}
  };

  ShelfConfig();

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

  ~ShelfConfig() override;

  static ShelfConfig* Get();

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Add observers to this objects's dependencies.
  void Init();

  // Remove observers from this object's dependencies.
  void Shutdown();

  // OverviewObserver:
  void OnOverviewModeWillStart() override;
  void OnOverviewModeEnding(OverviewSession* overview_session) override;

  void OnSplitViewStateChanged(SplitViewController::State previous_state,
                               SplitViewController::State state);

  // SessionObserver:
  void OnSessionStateChanged(session_manager::SessionState state) override;

  // DisplayObserver:
  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t changed_metrics) override;

  // VirtualKeyboardModel::Observer:
  void OnVirtualKeyboardVisibilityChanged() override;

  // AppListControllerObserver:
  void OnAppListVisibilityWillChange(bool shown, int64_t display_id) override;

  // Updates the shelf configuration to match the provided tablet mode state.
  // Called during transitions to enter or exit tablet mode.
  void UpdateForTabletMode(bool in_tablet_mode);

  // Whether the shelf control buttons must be shown for accessibility
  // reasons.
  bool ShelfControlsForcedShownForAccessibility() const;

  // Returns the optimal shelf button size for the given hotseat density.
  int GetShelfButtonSize(HotseatDensity density) const;

  // Returns the optimal shelf icon size for the given hotseat density.
  int GetShelfButtonIconSize(HotseatDensity density) const;

  // Returns the shelf shortuct icon size.
  int GetShelfShortcutIconSize() const;

  // Returns the shelf shortcut icon border size.
  int GetShelfShortcutIconBorderSize() const;

  // Returns the shelf shortcut host badge icon size.
  int GetShelfShortcutHostBadgeIconSize() const;

  // Returns the shelf shortcut host badge icon border size.
  int GetShelfShortcutHostBadgeBorderSize() const;

  // Returns the shelf shortcut bottom right corner radius.
  int GetShelfShortcutTeardropCornerRadiusSize() const;

  // Returns the hotseat height for the given hotseat density.
  // NOTE: This may not match the actual hotseat size, as hotseat may get scaled
  // down if it does not fit in available bounds within the shelf. Use
  // HotseatWidget::GetHotseatSize() to get the actual widget size.
  int GetHotseatSize(HotseatDensity density) const;

  // Returns the padding between the shelf and elevated homecher.
  int GetHomecherElevatedAppBarOffset() const;

  // Size of the shelf when visible (height when the shelf is horizontal and
  // width when the shelf is vertical).
  int shelf_size() const;

  // Size of the shelf when an app is visible in tablet mode.
  int in_app_shelf_size() const;

  // Size of the shelf when not in tablet mode, or when no apps are visible.
  int system_shelf_size() const;

  // The shelf size within which the drag handle should be centered.
  int shelf_drag_handle_centering_size() const;

  // The size of the gap between the hotseat and shelf when the hotseat is
  // extended.
  int hotseat_bottom_padding() const;

  // Size of the space between buttons on the shelf.
  int button_spacing() const;

  // Size for controls like the home button, back button, etc.
  int control_size() const;

  // The radius of shelf control buttons.
  int control_border_radius() const;

  // The spacing between the edge of the shelf and the control buttons. When
  // shelf is horizontal, the left/right edges of the shelf are considered a
  // primary axis edge. When shelf is vertical, the top/bottom edges are
  // considered the primary axis edge.
  int control_button_edge_spacing(bool is_primary_axis_edge) const;

  // The duration of the hotseat background animations in ms.
  base::TimeDelta hotseat_background_animation_duration() const;

  // The duration of the shelf show/hide animation in ms.
  base::TimeDelta shelf_animation_duration() const;

  // The extra padding added to status area tray buttons on the shelf.
  int status_area_hit_region_padding() const;

  // The threshold relative to the size of the shelf that is used to determine
  // if the shelf visibility should change during a drag.
  float drag_hide_ratio_threshold() const;

  int workspace_area_visible_inset() const {
    return workspace_area_visible_inset_;
  }
  int workspace_area_auto_hide_inset() const {
    return workspace_area_auto_hide_inset_;
  }
  int hidden_shelf_in_screen_portion() const {
    return hidden_shelf_in_screen_portion_;
  }
  int status_indicator_offset_from_shelf_edge() const {
    return status_indicator_offset_from_shelf_edge_;
  }
  int scrollable_shelf_ripple_padding() const {
    return scrollable_shelf_ripple_padding_;
  }
  int shelf_tooltip_preview_height() const {
    return shelf_tooltip_preview_height_;
  }
  int shelf_tooltip_preview_max_width() const {
    return shelf_tooltip_preview_max_width_;
  }
  float shelf_tooltip_preview_max_ratio() const {
    return shelf_tooltip_preview_max_ratio_;
  }
  float shelf_tooltip_preview_min_ratio() const {
    return shelf_tooltip_preview_min_ratio_;
  }
  int shelf_blur_radius() const { return shelf_blur_radius_; }
  int mousewheel_scroll_offset_threshold() const {
    return mousewheel_scroll_offset_threshold_;
  }
  int in_app_control_button_height_inset() const {
    return in_app_control_button_height_inset_;
  }

  bool is_dense() const { return is_dense_; }

  bool is_in_app() const { return is_in_app_; }

  bool in_split_view_with_overview() const {
    return in_split_view_with_overview_;
  }

  bool shelf_controls_shown() const { return shelf_controls_shown_; }

  bool is_virtual_keyboard_shown() const { return is_virtual_keyboard_shown_; }

  bool in_tablet_mode() const { return in_tablet_mode_; }

  bool in_overview_mode() const { return overview_mode_; }

  bool elevate_tablet_mode_app_bar() const {
    return elevate_tablet_mode_app_bar_;
  }

  // Gets the current color for the shelf control buttons.
  SkColor GetShelfControlButtonColor(const views::Widget* widget) const;

  // Gets the shelf color when a window is maximized.
  SkColor GetMaximizedShelfColor(const views::Widget* widget) const;

  // Gets the ColorId for shelf color.
  ui::ColorId GetShelfBaseLayerColorId() const;

  // Gets the default shelf color, calculated using the wallpaper color if
  // available.
  SkColor GetDefaultShelfColor(const views::Widget* widget) const;

  // Returns the current blur radius to use for the control buttons.
  int GetShelfControlButtonBlurRadius() const;

  // The padding between the app icon and the end of the scrollable shelf.
  int GetAppIconEndPadding() const;

  // Returns the margin on either side of the group of app icons.
  int GetAppIconGroupMargin() const;

  // The animation time for dimming shelf icons, widgets, and buttons.
  base::TimeDelta DimAnimationDuration() const;

  // The tween type for dimming shelf icons, widgets, and buttons.
  gfx::Tween::Type DimAnimationTween() const;

  // The size of the shelf drag handle.
  gfx::Size DragHandleSize() const;

  // Size of the shelf in tablet mode.
  int GetSystemShelfSizeInTabletMode() const;

  // Records the UMA of showing the stacked hotseat app bar and returns the size
  // of the insets used in tablet mode to allocate space to the shelf.
  int GetTabletModeShelfInsetsAndRecordUMA();

  // Minimum size for the inline app bar.
  int GetMinimumInlineAppBarSize() const;

  // Updates 'elevate_tablet_mode_app_bar_' for `inline_app_bar_size`.
  void UpdateShowElevatedAppBar(const gfx::Size& inline_app_bar_size);

 private:
  friend class ShelfConfigTest;

  class ShelfAccessibilityObserver;
  class ShelfSplitViewObserver;

  // Called whenever something has changed in the shelf configuration. Notifies
  // all observers.
  void OnShelfConfigUpdated();

  // Updates |is_dense_|, |is_app_list_visible_|, and |shelf_controls_shown_|
  // and notifies all observers of the update if the state changes.
  // |new_is_app_list_visible| - The new app list visibility state.
  // |tablet_mode_changed| should be set to true if this config is being updated
  // as a result of a change in tablet mode state.
  void UpdateConfig(bool new_is_app_list_visible, bool tablet_mode_changed);

  // Gets the current shelf size.
  // |ignore_in_app_state| - Whether the returned shelf size should be
  //                         calculated as if is_in_app() returns false.
  int GetShelfSize(bool ignore_in_app_state) const;

  // Updates shelf config - called when the accessibility state changes.
  void UpdateConfigForAccessibilityState();

  // Calculates the intended in-app state with the provided app list and virtual
  // keyboard visibility.
  bool CalculateIsInApp(bool app_list_visible,
                        bool virtual_keyboard_shown) const;

  // Whether an elevated app bar has been rendered (stacked hotseat). This
  // boolean is used for logging UMA metrics.
  std::optional<bool> has_shown_elevated_app_bar_;

  // Whether tablet mode homecher should use elevated app bar.
  bool elevate_tablet_mode_app_bar_ = false;

  // Whether the in app shelf should be shown in overview mode.
  bool use_in_app_shelf_in_overview_ = false;

  // True if device is currently in overview mode.
  bool overview_mode_ = false;

  // True if device is currently in tablet mode.
  bool in_tablet_mode_ = false;

  // Whether shelf is currently standard or dense.
  bool is_dense_ = false;

  // Whether the shelf is currently in in-app state.
  bool is_in_app_ = false;

  // Whether the device is in split view. Only tracked in overview mode.
  bool in_split_view_with_overview_ = false;

  // Whether the shelf buttons (navigation controls, and overview tray button)
  // should be shown.
  bool shelf_controls_shown_ = false;

  // Whether virtual IME keyboard is shown.
  bool is_virtual_keyboard_shown_ = false;

  // Whether the app list (or home launcher in tablet mode) is visible.
  bool is_app_list_visible_ = false;

  // Size of the icons within shelf buttons.
  const int shelf_button_icon_size_;
  const int shelf_button_icon_size_median_;
  const int shelf_button_icon_size_dense_;

  // Size of the shortcut icon.
  const int shelf_shortcut_icon_size_;

  // Size of the shortcut icon border.
  const int shelf_shortcut_icon_border_size_;

  // Size of the shortcut host badge icon.
  const int shelf_shortcut_host_badge_icon_size_;

  // Size of the shortcut host badge border.
  const int shelf_shortcut_host_badge_border_size_;

  // Size of the bottom right corner radius of a shortcut.
  const int shelf_shortcut_teardrop_corner_radius_;

  // Size allocated for each app button on the shelf.
  const int shelf_button_size_;
  const int shelf_button_size_median_;
  const int shelf_button_size_dense_;

  // Size of the space between buttons on the shelf.
  const int shelf_button_spacing_;

  // The extra padding added to status area tray buttons on the shelf.
  const int shelf_status_area_hit_region_padding_;
  const int shelf_status_area_hit_region_padding_dense_;

  // The margin on either side of the group of app icons in tablet/clamshell.
  const int app_icon_group_margin_tablet_;
  const int app_icon_group_margin_clamshell_;

  // We reserve a small area on the edge of the workspace area to ensure that
  // the resize handle at the edge of the window can be hit.
  const int workspace_area_visible_inset_;

  // When autohidden we extend the touch hit target onto the screen so that the
  // user can drag the shelf out.
  const int workspace_area_auto_hide_inset_;

  // Portion of the shelf that's within the screen bounds when auto-hidden.
  const int hidden_shelf_in_screen_portion_;

  // The distance between the edge of the shelf and the status indicators.
  const int status_indicator_offset_from_shelf_edge_;

  // Padding between the shelf container view and the edging app icon in order
  // to show the app icon's ripple correctly.
  const int scrollable_shelf_ripple_padding_;

  // Dimensions for hover previews.
  const int shelf_tooltip_preview_height_;
  const int shelf_tooltip_preview_max_width_;
  const float shelf_tooltip_preview_max_ratio_;
  const float shelf_tooltip_preview_min_ratio_;

  // The blur radius used for the shelf.
  const int shelf_blur_radius_;

  // The threshold at which mousewheel and touchpad scrolls are either ignored
  // or acted upon.
  const int mousewheel_scroll_offset_threshold_;

  // The height inset on the control buttons when in-app shelf is shown.
  const int in_app_control_button_height_inset_;

  // The padding between the app icon and the end of the scrollable shelf in
  // tablet mode.
  const int app_icon_end_padding_;

  // Object responsible for observing accessibility settings relevant to shelf
  // config.
  std::unique_ptr<ShelfAccessibilityObserver> accessibility_observer_;

  // Object responsible for observing overview mode split state changes relevant
  // to shelf config.
  std::unique_ptr<ShelfSplitViewObserver> split_view_observer_;

  // Receive callbacks from DisplayObserver.
  display::ScopedDisplayObserver display_observer_{this};

  base::ObserverList<Observer> observers_;
};

}  // namespace ash

#endif  // ASH_PUBLIC_CPP_SHELF_CONFIG_H_