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
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163

ash / wm / desks / desk_bar_controller.h [blame]

// 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_WM_DESKS_DESK_BAR_CONTROLLER_H_
#define ASH_WM_DESKS_DESK_BAR_CONTROLLER_H_

#include <memory>
#include <optional>
#include <vector>

#include "ash/ash_export.h"
#include "ash/shell_observer.h"
#include "ash/wm/desks/desk_bar_view_base.h"
#include "ash/wm/desks/desks_controller.h"
#include "ash/wm/desks/window_occlusion_calculator.h"
#include "ash/wm/overview/overview_observer.h"
#include "base/memory/raw_ptr.h"
#include "ui/display/display_observer.h"
#include "ui/events/event_handler.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/public/activation_change_observer.h"

namespace aura {
class Window;
}  // namespace aura

namespace display {
enum class TabletState;
}  // namespace display

namespace ash {

class DeskButtonContainer;

// Controller for the desk bars that is responsible for creating, destroying,
// and managing all desk bars. At this point, it supports only desk button desk
// bar, but eventually, it will support all bars. Please note this controller is
// owned by `DesksController`.
class ASH_EXPORT DeskBarController : public DesksController::Observer,
                                     public ui::EventHandler,
                                     public OverviewObserver,
                                     public ShellObserver,
                                     public wm::ActivationChangeObserver,
                                     public display::DisplayObserver {
 public:
  struct BarWidgetAndView {
    BarWidgetAndView(DeskBarViewBase* bar_view,
                     std::unique_ptr<views::Widget> bar_widget);
    BarWidgetAndView(BarWidgetAndView&& other);
    BarWidgetAndView& operator=(BarWidgetAndView&& other);
    BarWidgetAndView(const BarWidgetAndView&) = delete;
    BarWidgetAndView& operator=(const BarWidgetAndView&) = delete;
    ~BarWidgetAndView();

    // Returns the next focusable view based on `starting_view`, which is a
    // focusable view in `bar_view`, and `reverse`. If `reverse` is false, it
    // returns the traversible view after `starting_view`; otherwise, it returns
    // the traversible view before `starting_view`.
    const views::View* GetNextFocusableView(views::View* starting_view,
                                            bool reverse) const;

    // Returns the first focusable view in `bar_view`.
    const views::View* GetFirstFocusableView() const;

    // Returns the last focusable view in `bar_view`.
    const views::View* GetLastFocusableView() const;

    std::unique_ptr<views::Widget> bar_widget;
    raw_ptr<DeskBarViewBase> bar_view;
  };

  DeskBarController();

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

  ~DeskBarController() override;

  // DesksController::Observer:
  void OnDeskSwitchAnimationLaunching() override;

  // ui::EventHandler:
  void OnMouseEvent(ui::MouseEvent* event) override;
  void OnTouchEvent(ui::TouchEvent* event) override;
  void OnKeyEvent(ui::KeyEvent* event) override;

  // OverviewObserver:
  void OnOverviewModeWillStart() override;

  // ShellObserver:
  void OnShellDestroying() override;

  // wm::ActivationChangeObserver:
  void OnWindowActivated(ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override;

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

  // Returns desk bar view in `root`. If there is no such desk bar, nullptr is
  // returned.
  DeskBarViewBase* GetDeskBarView(aura::Window* root);

  // Returns true when there is a visible desk bar.
  bool IsShowingDeskBar() const;

  // Creates and shows the desk bar in 'root'.
  void OpenDeskBar(aura::Window* root);

  // Hides and destroys the desk bar in 'root'.
  void CloseDeskBar(aura::Window* root);

  // Hides and destroys all desk bars.
  void CloseAllDeskBars();

 private:
  // Moves the focus ring to the next traversable view.
  void MoveFocus(const BarWidgetAndView& desk_bar, bool reverse);

  void CloseDeskBarInternal(BarWidgetAndView& desk_bar);

  // Common handling of mouse and touch events.
  void OnLocatedEvent(ui::LocatedEvent& event);

  // When pressing off the bar, it should either commit desk name change, or
  // hide the bar.
  void OnMaybePressOffBar(ui::LocatedEvent& event);

  // Returns desk button container for `root`.
  DeskButtonContainer* GetDeskButtonContainer(aura::Window* root);

  // Updates desk button activation.
  void SetDeskButtonActivation(aura::Window* root, bool is_activated);

  // Bar widgets and bar views for the desk bars. Right now, it supports only
  // desk button desk bar. Support for overview desk bar will be added later.
  std::vector<BarWidgetAndView> desk_bars_;

  // Observes display configuration changes.
  display::ScopedDisplayObserver display_observer_{this};

  // Root window of the desk button that is clicked. This is used to determine
  // which desk button should gain focus back after the desk bar is closed.
  raw_ptr<aura::Window> desk_button_root_ = nullptr;

  // True if the desk button should acquire focus back when hitting esc.
  bool should_desk_button_acquire_focus_ = false;

  // Indicates that shell is destroying.
  bool is_shell_destroying_ = false;

  bool should_ignore_activation_change_ = false;

  std::optional<WindowOcclusionCalculator> window_occlusion_calculator_;
};

}  // namespace ash

#endif  // ASH_WM_DESKS_DESK_BAR_CONTROLLER_H_