910e62b5创建于 1月15日历史提交
// Copyright 2023 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_DESK_BUTTON_WIDGET_H_
#define ASH_SHELF_DESK_BUTTON_WIDGET_H_

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

namespace ash {

class DeskButtonContainer;
class DeskButtonWidget;
class Shelf;
enum class ShelfAlignment;

// Delegate view for laying out the desk button UI. It does not use the default
// fill layout since the desk button UI has dynamic size, and the widget
// reserves the maximum possible space for the current shelf alignment and zero
// state.
class DeskButtonWidgetDelegateView : public views::WidgetDelegateView {
 public:
  DeskButtonWidgetDelegateView();
  DeskButtonWidgetDelegateView(const DeskButtonWidgetDelegateView&) = delete;
  DeskButtonWidgetDelegateView& operator=(const DeskButtonWidgetDelegateView&) =
      delete;
  ~DeskButtonWidgetDelegateView() override;

  DeskButtonContainer* desk_button_container() const {
    return desk_button_container_;
  }

  // Initializes the view. Must be called before any meaningful UIs can be
  // laid out.
  void Init(DeskButtonWidget* desk_button_widget);

  // views::WidgetDelegateView:
  void Layout(PassKey) override;

  // views::View:
  bool AcceleratorPressed(const ui::Accelerator& accelerator) override;

 private:
  raw_ptr<DeskButtonContainer> desk_button_container_ = nullptr;
  raw_ptr<DeskButtonWidget> desk_button_widget_ = nullptr;
};

// The desk button provides an overview of existing desks and quick access to
// them. The button is only visible in clamshell mode and disappears when in
// overview.
class ASH_EXPORT DeskButtonWidget : public ShelfComponent,
                                    public views::Widget {
 public:
  explicit DeskButtonWidget(Shelf* shelf);
  DeskButtonWidget(const DeskButtonWidget&) = delete;
  DeskButtonWidget& operator=(const DeskButtonWidget&) = delete;
  ~DeskButtonWidget() override;

  // Returns the max length for the widget for the horizontal or vertical shelf.
  static int GetMaxLength(bool horizontal_shelf);

  DeskButtonWidgetDelegateView* delegate_view() const { return delegate_view_; }

  Shelf* shelf() const { return shelf_; }

  // Indicates if the shelf should reserve some space for this widget.
  bool ShouldReserveSpaceFromShelf() const;

  // Whether the desk button should currently be visible.
  bool ShouldBeVisible() const;

  // Updates expanded state and values impacted by shelf alignment change.
  void PrepareForAlignmentChange();

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

  // Called when shelf layout manager detects a locale change.
  void HandleLocaleChange();

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

  DeskButtonContainer* GetDeskButtonContainer() const;

  // Returns true if this widget belongs to a horizontal shelf.
  bool IsHorizontalShelf() const;

  void SetDefaultChildToFocus(views::View* default_child_to_focus);

  // Stores the current focused view for desk button widget.
  void StoreDeskButtonFocus();

  // Restores focus to the stored focused view of desk button widget if there is
  // one.
  void RestoreDeskButtonFocus();

  // Depending on what child view has focus, either focus out of the desk
  // button, or pass the focus to the next view. `reverse` indicates backward
  // focusing, otherwise forward focusing.
  void MaybeFocusOut(bool reverse);

  // Sets previous focus and next focus of desk button.
  void InitializeAccessibleProperties();

 private:
  // views::Widget:
  bool OnNativeWidgetActivationChanged(bool active) override;

  raw_ptr<DeskButtonWidgetDelegateView, DanglingUntriaged> delegate_view_ =
      nullptr;

  gfx::Rect target_bounds_;

  raw_ptr<Shelf> const shelf_;

  // Default child view to focus when `OnNativeWidgetActivationChanged()`
  // occurs. When it's not null, it should point to the desk button, the
  // previous desk button, or the next desk button.
  raw_ptr<views::View> default_child_to_focus_ = nullptr;

  // Stored focused view for the widget. This is used to restore the focus to
  // the desk button when the desk bar is closed. When it's not null, it should
  // point to the desk button, the previous desk button, or the next desk
  // button.
  raw_ptr<views::View> stored_focused_view_ = nullptr;
};

}  // namespace ash

#endif  // ASH_SHELF_DESK_BUTTON_WIDGET_H_